home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright (C) 1990 C van Reewijk, email: dutentb.uucp!reeuwijk
-
- This file is part of GLASS.
-
- GLASS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- GLASS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GLASS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- /* file: propt.c
- *
- * Standard handler for optimized printing of datastructures.
- */
-
- /* Standard UNIX libraries */
- #include <stdio.h>
- #include <ctype.h>
-
- /* Local definitions */
- #include "tmc.h"
- #include "config.h"
-
- static char fatalerrm[] = "*** fatal error: %s ***\n";
- #define FATAL(msg) { fprintf(stderr,fatalerrm,msg); exit(1); }
-
- /* the possible error messages */
- static char badtag[] = "bad tag: %d";
- static char badtagspc[30]; /* to store output of format string above */
- static char outofmemory[] = "out of memory";
-
- #define FATALTAG(tag) {(void) sprintf(badtagspc,badtag,tag); FATAL(badtagspc);}
-
- /* statistics */
-
- /* width of a tab as generated by '\t' */
- #define TABWIDTH 8
-
- #ifndef TRUE
- #define TRUE 1
- #endif
- #ifndef FALSE
- #define FALSE 0
- #endif
-
- typedef short bool;
-
- static char *linebuf = (char *) 0;
-
- /* datastructures */
- typedef struct str_Sstack *Sstack;
- typedef struct str_sunit *sunit;
- typedef struct str_SuWord *SuWord;
- typedef struct str_SuCons *SuCons;
- typedef struct str_SuList *SuList;
- typedef struct str_SuTuple *SuTuple;
-
- #define SstackNIL (Sstack)0
- #define sunitNIL (sunit)0
- #define SuWordNIL (SuWord)0
- #define SuConsNIL (SuCons)0
- #define SuListNIL (SuList)0
-
- typedef struct str_Sstack {
- Sstack next;
- sunit ulist;
- };
-
- typedef struct str_sunit {
- sunit next;
- int tag;
- };
-
- /* possible tags for sunit: */
- #define TAGSuWord 1
- #define TAGSuCons 2
- #define TAGSuList 3
- #define TAGSuTuple 4
-
- typedef struct str_SuWord {
- sunit next;
- int tag;
- string word;
- };
-
- typedef struct str_SuCons {
- sunit next;
- int tag;
- sunit ulist;
- };
-
- typedef struct str_SuList {
- sunit next;
- int tag;
- sunit ulist;
- };
-
- typedef struct str_SuTuple {
- sunit next;
- int tag;
- sunit ulist;
- };
-
- /* local variables of printopt. */
- static FILE *so_file; /* output file */
- static int so_istep; /* indent step */
- static int so_width; /* with of output */
- static int braclev; /* current bracket level */
- static sunit curlist; /* current list of units */
- static Sstack stack; /* stack of open constr. & lists */
-
- /* prototypes are concentrated in one place to make it easy
- * for the preprocessor.
- */
- #if defined( __STDC__ ) && __STDC__>0
- /* allocate routines */
- static Sstack newSstack( sunit u );
- static sunit newSuWord( string s );
- static sunit newSuCons( sunit u );
- static sunit newSuList( sunit l );
- static sunit newSuTuple( sunit l );
- static void rfresunit( sunit e );
-
- /* recursive free routines */
- static void rfreSuWord( SuWord e );
- static void rfreSuCons( SuCons e );
- static void rfreSuList( SuList l );
- static void rfreSuTuple( SuTuple t );
- static void rfresunit_list( sunit l );
-
- static sunit appsunitlist( sunit a, sunit b );
-
- static int lenlist( sunit l );
- static void doindent( int n );
-
- static void pushlev( void );
- static void poplev( void );
- static int lencons( sunit l );
- static int lentuple( sunit l );
- static void vertprintcons( SuCons c, int lev );
- static void vertprinttuple( SuTuple t, int lev );
- static void vertprintlist( SuList lst, int lev );
- static void vertprintsunit( sunit e, int lev );
- static char *horprintcons( sunit l );
- static char *horprinttuple( sunit l );
- static char *horprintlist( sunit l );
- #else
- /* allocate routines */
- static Sstack newSstack();
- static sunit newSuWord();
- static sunit newSuCons();
- static sunit newSuList();
- static sunit newSuTuple();
-
- /* recursive free routines */
- static void rfreSuWord();
- static void rfreSuCons();
- static void rfreSuList();
- static void rfreSuTuple();
- static void rfresunit_list();
- #endif
-
- /*******************************************************************\
- * Allocation routines *
- \*******************************************************************/
-
- static Sstack newSstack( par_ulist )
- sunit par_ulist;
- {
- Sstack new;
-
- new = (Sstack) malloc( sizeof(*new));
- if( (char *)new == (char *)0 ) FATAL( outofmemory );
- new->next = SstackNIL;
- new->ulist = par_ulist;
- return( (Sstack) new );
- }
-
- static sunit newSuWord( par_word )
- string par_word;
- {
- SuWord new;
-
- new = (SuWord) malloc( sizeof(*new));
- if( (char *)new == (char *)0 ) FATAL( outofmemory );
- new->next = sunitNIL;
- new->tag = TAGSuWord;
- new->word = par_word;
- return( (sunit) new );
- }
-
- static sunit newSuCons( par_ulist )
- sunit par_ulist;
- {
- SuCons new;
-
- new = (SuCons) malloc( sizeof(*new));
- if( (char *)new == (char *)0 ) FATAL( outofmemory );
- new->next = sunitNIL;
- new->tag = TAGSuCons;
- new->ulist = par_ulist;
- return( (sunit) new );
- }
-
- static sunit newSuList( par_ulist )
- sunit par_ulist;
- {
- SuList new;
-
- new = (SuList) malloc( sizeof(*new));
- if( (char *)new == (char *)0 ) FATAL( outofmemory );
- new->next = sunitNIL;
- new->tag = TAGSuList;
- new->ulist = par_ulist;
- return( (sunit) new );
- }
-
- static sunit newSuTuple( par_ulist )
- sunit par_ulist;
- {
- SuTuple new;
-
- new = (SuTuple) malloc( sizeof(*new));
- if( (char *)new == (char *)0 ) FATAL( outofmemory );
- new->next = sunitNIL;
- new->tag = TAGSuTuple;
- new->ulist = par_ulist;
- return( (sunit) new );
- }
-
- /*******************************************************************\
- * Freeing routines *
- \*******************************************************************/
-
- #define freSstack(e) TMFREE( e );
- #define freSuWord(e) TMFREE( e );
- #define freSuCons(e) TMFREE( e );
- #define freSuList(e) TMFREE( e );
- #define freSuTuple(e) TMFREE( e );
-
- /*******************************************************************\
- * Recursive freeing routines *
- \*******************************************************************/
-
- /* free an element of type sunit, constructor SuWord, and all elements
- in the constructor.
- */
- static void rfreSuWord( e )
- SuWord e;
- {
- fre_string( e->word );
- freSuWord( e );
- }
-
- /* free an element of type sunit, constructor SuCons, and all elements in the constructor
- */
- static void rfreSuCons( e )
- SuCons e;
- {
- rfresunit_list( e->ulist );
- freSuCons( e );
- }
-
- /* free an element of type sunit, constructor SuList, and all elements in the
- constructor
- */
- static void rfreSuList( e )
- SuList e;
- {
- rfresunit_list( e->ulist );
- freSuList( e );
- }
-
- /* free an element of type sunit, constructor SuTuple, and all elements in the
- constructor
- */
- static void rfreSuTuple( e )
- SuTuple e;
- {
- rfresunit_list( e->ulist );
- freSuTuple( e );
- }
-
-
- /* recursively free an element of type sunit
- and all elements in it.
- */
- static void rfresunit( e )
- sunit e;
- {
- switch( e->tag ){
- case TAGSuWord:
- rfreSuWord( (SuWord) e );
- break;
-
- case TAGSuCons:
- rfreSuCons( (SuCons) e );
- break;
-
- case TAGSuList:
- rfreSuList( (SuList) e );
- break;
-
- case TAGSuTuple:
- rfreSuTuple( (SuTuple) e );
- break;
-
- default:
- FATALTAG( e->tag );
- }
- }
-
- /* recursively free a list of elements of type sunit */
- static void rfresunit_list( e )
- sunit e;
- {
- sunit n;
-
- while( e!=sunitNIL ){
- n = e->next;
- rfresunit( e );
- e = n;
- }
- }
-
- /*******************************************************************\
- * Append routines *
- \*******************************************************************/
-
- /* append list of sunit 'b' after list of sunit 'a' */
- static sunit appsunitlist( a, b )
- sunit a;
- sunit b;
- {
- sunit tl;
-
- if( a == sunitNIL ) return( b );
- tl = a;
- while( tl->next != sunitNIL ) tl = tl->next;
- tl->next = b;
- return( a );
- }
-
- static void doindent( n )
- int n;
- {
- while( n >= TABWIDTH ){
- fputc( '\t', so_file );
- n -= TABWIDTH;
- }
- while( n > 0 ){
- fputc( ' ', so_file );
- n--;
- }
- }
-
- /******************************************************
- * DETERMINATION OF STRING LENGTH *
- ******************************************************/
-
- /* Determine the length of a constructor string when printed
- on one line.
-
- This is done as follows:
- - the length of a list containing sub-lists is 0.
- - the length of a constructor without members is 2 (for the brackets).
- - For a word list of length 1 the length is the length of the word.
- - Otherwise the opening and closing brackets cause an overhead
- of 2 spaces.
- - Each word adds its string length.
- - All words are separated by 1 space.
-
- When counting a space for each word in the list, the netto overhead
- of the brackets is 1 spaces.
- */
- static int lencons( l )
- sunit l;
- {
- int len = 1; /* overhead */
-
- if( l == sunitNIL ) return( 2 );
- if( l->next == sunitNIL && l->tag == TAGSuWord )
- return( (int) strlen( ((SuWord)l)->word ) );
- while( l != sunitNIL ){
- if( l->tag != TAGSuWord ) return( 0 );
- len += 1 + (int) strlen( ((SuWord)l)->word );
- l = l->next;
- }
- return( len );
- }
-
- /* Determine the length of a list string when printed
- on one line.
-
- This is done as follows:
- - The length of a list containing sub-lists is 0.
- - For a word list of length 0 the length is 2 (since "[]" is printed).
- - Otherwise the opening and closing brackets cause an overhead
- of 2 spaces.
- - Each word adds its string length.
- - All words are separated by 1 comma and 1 space.
-
- When counting a space and comma for each word in the list,
- the netto overhead of the brackets is 0 spaces.
- */
- static int lenlist( l )
- sunit l;
- {
- int len = 0; /* overhead */
-
- if( l == sunitNIL ) return( 2 );
- while( l != sunitNIL ){
- if( l->tag != TAGSuWord ) return( 0 );
- len += 2 + (int) strlen( ((SuWord)l)->word );
- l = l->next;
- }
- return( len );
- }
-
- /* Determine the length of a tuple string when printed
- on one line.
-
- This is done as follows:
- - The length of a tuple containing sub-tuples is 0.
- - For a word tuple of length 0 the length is 2 (since "()" is printed).
- - Otherwise the opening and closing brackets cause an overhead
- of 2 spaces.
- - Each word adds its string length.
- - All words are separated by 1 comma and 1 space.
-
- When counting a space and comma for each word in the list,
- the netto overhead of the brackets is 0 spaces.
- */
- static int lentuple( l )
- sunit l;
- {
- int len = 0; /* overhead */
-
- if( l == sunitNIL ) return( 2 );
- while( l != sunitNIL ){
- if( l->tag != TAGSuWord ) return( 0 );
- len += 2 + (int) strlen( ((SuWord)l)->word );
- l = l->next;
- }
- return( len );
- }
-
- /******************************************************
- * HORIZONTAL PRINTING ROUTINE *
- ******************************************************/
-
- static void vertprintsunit();
-
- /* Print constructor 'c' in vertical mode. */
- static void vertprintcons( c, lev )
- SuCons c;
- int lev;
- {
- sunit l;
-
- l = c->ulist;
- if( l != sunitNIL && l->next == sunitNIL ){
- vertprintsunit( l, lev );
- return;
- }
- doindent( so_istep * lev );
- fputs( "(\n", so_file );
- while( l != sunitNIL ){
- vertprintsunit( l, (lev+1) );
- fputc( '\n', so_file );
- l = l->next;
- }
- doindent( so_istep * lev );
- fputc( ')', so_file );
- return;
- }
-
- /* Print list 'lst' in vertical mode. */
- static void vertprintlist( lst, lev )
- SuList lst;
- int lev;
- {
- sunit l;
-
- l = lst->ulist;
- if( l == sunitNIL ){
- doindent( so_istep * lev );
- fputs( "[]", so_file );
- return;
- }
- doindent( so_istep * lev );
- fputs( "[\n", so_file );
- while( l != sunitNIL ){
- vertprintsunit( l, (lev+1) );
- l = l->next;
- if( l != sunitNIL ) fputc( ',', so_file );
- fputc( '\n', so_file );
- }
- doindent( so_istep * lev );
- fputc( ']', so_file );
- return;
- }
-
- /* Print tuple 'tpl' in vertical mode. */
- static void vertprinttuple( lst, lev )
- SuTuple lst;
- int lev;
- {
- sunit l;
-
- l = lst->ulist;
- if( l == sunitNIL ){
- doindent( so_istep * lev );
- fputs( "()", so_file );
- return;
- }
- doindent( so_istep * lev );
- fputs( "(\n", so_file );
- while( l != sunitNIL ){
- vertprintsunit( l, (lev+1) );
- l = l->next;
- if( l != sunitNIL ) fputc( ',', so_file );
- fputc( '\n', so_file );
- }
- doindent( so_istep * lev );
- fputc( ')', so_file );
- return;
- }
-
- /* Given a unit 'l' and a indent level 'lev', print given
- unit to 'so_file'. When neccary delegate printing to
- specialized routines 'vertprint{list,tuple,cons}()'.
-
- NOTE: no return is printed after the last line, so
- that a comma can be appended when necessary.
- */
- static void vertprintsunit( l, lev )
- sunit l;
- int lev;
- {
- switch( l->tag ){
- case TAGSuWord:
- doindent( so_istep * lev );
- fputs( ((SuWord)l)->word, so_file );
- break;
-
- case TAGSuCons:
- vertprintcons( (SuCons) l, lev );
- break;
-
- case TAGSuList:
- vertprintlist( (SuList) l, lev );
- break;
-
- case TAGSuTuple:
- vertprinttuple( (SuTuple) l, lev );
- break;
- }
- }
-
- /* Print list consisting of sunits in 'l' in
- horizontal mode, and return a new string for it.
- */
- static char *horprintlist( l )
- sunit l;
- {
- char *bufp;
- char *v;
-
- if( l == sunitNIL ) return( new_string( "[]" ) );
- bufp = linebuf;
- *bufp++ = '[';
- while( l != sunitNIL ){
- v = ((SuWord)l)->word;
- while( *v ) *bufp++ = *v++;
- l = l->next;
- if( l != sunitNIL ){
- *bufp++ = ',';
- *bufp++ = ' ';
- }
- }
- *bufp++ = ']';
- *bufp = '\0';
- return( new_string( linebuf ) );
- }
-
- /* Print tuple consisting of sunits in 'l' in
- horizontal mode, and return a new string for it.
- */
- static char *horprinttuple( l )
- sunit l;
- {
- char *bufp;
- char *v;
-
- if( l == sunitNIL ) return( new_string( "()" ) );
- bufp = linebuf;
- *bufp++ = '(';
- while( l != sunitNIL ){
- v = ((SuWord)l)->word;
- while( *v ) *bufp++ = *v++;
- l = l->next;
- if( l != sunitNIL ){
- *bufp++ = ',';
- *bufp++ = ' ';
- }
- }
- *bufp++ = ')';
- *bufp = '\0';
- return( new_string( linebuf ) );
- }
-
- /* Print constructor consisting of sunits in 'l' in
- horizontal mode, and return a new string for it.
- */
- static char *horprintcons( l )
- sunit l;
- {
- char *bufp;
- char *v;
-
- if( l == sunitNIL ) return( new_string( "()" ) );
- if( l->next == sunitNIL ) return( new_string( ((SuWord)l)->word ) );
- bufp = linebuf;
- *bufp++ = '(';
- while( l != sunitNIL ){
- v = ((SuWord)l)->word;
- while( *v ) *bufp++ = *v++;
- l = l->next;
- if( l != sunitNIL ) *bufp++ = ' ';
- }
- *bufp++ = ')';
- *bufp = '\0';
- return( new_string( linebuf ) );
- }
-
- /******************************************************
- * STACK MANAGEMENT ROUTINES *
- ******************************************************/
-
- /* push current level on stack */
- static void pushlev()
- {
- register Sstack new;
-
- new = newSstack( curlist );
- new->next = stack;
- stack = new;
- }
-
- static void poplev()
- {
- Sstack e;
-
- if( stack == SstackNIL ) FATAL( "pop of empty printstack" );
- e = (Sstack) stack;
- curlist = e->ulist;
- stack = e->next;
- freSstack( (Sstack) e );
- }
-
- /******************************************************
- * TOP LEVEL ROUTINES *
- ******************************************************/
-
- /* start a new constructor */
- void opencons()
- {
- pushlev();
- braclev++;
- curlist = sunitNIL;
- }
-
- /* terminate current constructor */
- void closecons()
- {
- register sunit new;
- register int len;
-
- braclev--;
- len = lencons( curlist );
- if( len != 0 && (len + (braclev * so_istep)) < so_width ){
- new = newSuWord( horprintcons( curlist ) );
- rfresunit_list( curlist );
- }
- else {
- new = newSuCons( curlist );
- }
- poplev();
- if( braclev<1 ){
- vertprintsunit( new, 0 );
- fputc( '\n', so_file );
- rfresunit( new );
- return;
- }
- curlist = appsunitlist( curlist, new );
- }
-
- /* start a new list */
- void openlist()
- {
- pushlev();
- braclev++;
- curlist = sunitNIL;
- }
-
- /* terminate current list */
- void closelist()
- {
- register sunit new;
- register int len;
-
- braclev--;
- len = lenlist( curlist );
- if( len != 0 && (len + (braclev * so_istep)) < so_width ){
- new = newSuWord( horprintlist( curlist ) );
- rfresunit_list( curlist );
- }
- else {
- new = newSuList( curlist );
- }
- poplev();
- if( braclev<1 ){
- vertprintsunit( new, 0 );
- fputc( '\n', so_file );
- rfresunit( new );
- return;
- }
- curlist = appsunitlist( curlist, new );
- }
-
- /* start a new tuple */
- void opentuple()
- {
- pushlev();
- braclev++;
- curlist = sunitNIL;
- }
-
- /* terminate current tuple */
- void closetuple()
- {
- register sunit new;
- register int len;
-
- braclev--;
- len = lentuple( curlist );
- if( len != 0 && (len + (braclev * so_istep)) < so_width ){
- new = newSuWord( horprinttuple( curlist ) );
- rfresunit_list( curlist );
- }
- else {
- new = newSuTuple( curlist );
- }
- poplev();
- if( braclev<1 ){
- vertprintsunit( new, 0 );
- fputc( '\n', so_file );
- rfresunit( new );
- return;
- }
- curlist = appsunitlist( curlist, new );
- }
-
- /* add word 'w' to the current unit list, or print it
- directly if no brackets are opened.
- */
- void printword( w )
- char *w;
- {
- register sunit new;
-
- if( braclev<1 ){
- fputs( w, so_file );
- fputc( '\n', so_file );
- return;
- }
- new = newSuWord( new_string( w ) );
- curlist = appsunitlist( curlist, new );
- }
-
- void setprint( f, istep, width )
- FILE *f;
- int istep;
- int width;
- {
- so_file = f;
- so_istep = istep;
- so_width = width;
- braclev = 0;
- stack = SstackNIL;
- curlist = sunitNIL;
- if( linebuf != (char *)0 ){
- TMFREE( linebuf );
- }
- linebuf = malloc( (unsigned) width+10 );
- if( linebuf == (char *)0 ) FATAL( outofmemory );
- }
-